using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Text;
using System.Globalization;

using ca.metaobjects.csogateway;
using ca.metaobjects.csogateway.Converters.Interfaces;

namespace ca.metaobjects.csogateway.Converters.Collections
{
	/// <summary>
	/// <para>
	/// Provides methods to convert objects of various types into an instance of CsoGateway.Collections.List
	/// </para>
	/// 
	/// <para>
	/// Converter for
	/// <list type="bullet">
	/// <item>System.Collections.ArrayList</item>
	/// <item>System.Collections.Generic.List`1</item>
	/// <item>System.Collections.Specialized.StringCollection</item>
	/// </list>
	/// </para>
	///
	/// <para>
	/// Converts to
	/// <list type="bullet">
	/// <item>CsoGateway.Collections.List</item>
	/// </list>
	///	</para>
	/// 
	/// </summary>
	public class ListCollectionToClientSideConverter : IToClientSideConverter
	{
		/// <summary>
		/// Generates a string of javascript code that, when evaluated, creates an instance of CsoGateway.Collections.List
		/// that is the client side equivalent of the given object.
		/// The generated string is appended in the given StringBuffer. 
		/// </summary>
		/// <param name="sourceObject">An instance of one of the accepted types of list-like collections.</param>
		/// <param name="builder">The StringBuilder to write the generated javascript code to.</param>
		public void RenderObjectInstantiation(object sourceObject, StringBuilder builder)
		{
			IList listObject = (IList)sourceObject;

			builder.Append("new CsoGateway.Collections.List(");

			for (int i = 0; i < listObject.Count; ++i)
			{
				ToClientSideMainConverter.RenderCsoCompatibleObject(listObject[i], builder);

				if (i < listObject.Count - 1)
					builder.Append(',');
			}

			builder.Append(')');
		}
	}

	/// <summary>
	/// <para>
	/// Provides methods to convert an instance of System.Collections.Generic.LinkedList`1 into an instance of CsoGateway.Collections.List
	/// </para>
	/// 
	/// <para>
	/// Converter for
	/// <list type="bullet">
	/// <item>System.Collections.Generic.LinkedList`1</item>
	/// </list>
	/// </para>
	///
	/// <para>
	/// Converts to
	/// <list type="bullet">
	/// <item>CsoGateway.Collections.List</item>
	/// </list>
	/// </para>
	/// </summary>
	public class LinkedListCollectionToClientSideConverter : IToClientSideConverter
	{
		/// <summary>
		/// Generates a string of javascript code that, when evaluated, creates an instance of CsoGateway.Collections.List
		/// that is the client side equivalent of the given instance of System.Collections.Generic.LinkedList`1.
		/// The generated string is appended in the given StringBuffer. 
		/// </summary>
		/// <param name="sourceObject">An instance of System.Collections.Generic.LinkedList`1.</param>
		/// <param name="builder">The StringBuilder to write the generated javascript code to.</param>
		public void RenderObjectInstantiation(object sourceObject, StringBuilder builder)
		{
			ICollection linkedListObject = (ICollection)sourceObject;
			object[] arrayObject = new object[linkedListObject.Count];
			linkedListObject.CopyTo(arrayObject, 0);
			
			builder.Append("new CsoGateway.Collections.List(");

			for (int i = 0; i < arrayObject.Length; ++i)
			{
				ToClientSideMainConverter.RenderCsoCompatibleObject(arrayObject[i], builder);

				if (i < arrayObject.Length - 1)
					builder.Append(',');
			}
			
			builder.Append(')');
		}
	}

	/// <summary>
	/// <para>
	/// Provides methods to convert an instance of System.Collections.BitArray into an instance of CsoGateway.Collections.List
	/// </para>
	/// 
	/// <para>
	/// Converter for
	/// <list type="bullet">
	/// <item>System.Collections.BitArray</item>
	/// </list>
	/// </para>
	///
	/// <para>
	/// Converts to
	/// <list type="bullet">
	/// <item>CsoGateway.Collections.List</item>
	/// </list>
	/// </para>
	/// </summary>
	public class BitArrayToClientSideConverter : IToClientSideConverter
	{
		/// <summary>
		/// Generates a string of javascript code that, when evaluated, creates an instance of CsoGateway.Collections.List
		/// that is the client side equivalent of the given instance of System.Collections.BitArray.
		/// The generated string is appended in the given StringBuffer. 
		/// </summary>
		/// <param name="sourceObject">An instance of System.Collections.BitArray.</param>
		/// <param name="builder">The StringBuilder to write the generated javascript code to.</param>
		public void RenderObjectInstantiation(object sourceObject, StringBuilder builder)
		{
			BitArray bitArrayObject = (BitArray)sourceObject;

			builder.Append("new CsoGateway.Collections.List(");

			for (int i = 0; i < bitArrayObject.Count; ++i)
			{
				if (bitArrayObject.Get(i))
					builder.Append("true");
				else
					builder.Append("false");

				if (i < bitArrayObject.Count - 1)
					builder.Append(',');
			}

			builder.Append(')');
		}
	}

	/// <summary>
	/// <para>
	/// Provides methods to convert object of various types into an instance of CsoGateway.Collections.Dictionary
	/// </para>
	/// 
	/// <para>
	/// Converter for
	/// <list type="bullet">
	/// <item>System.Collections.Hashtable</item>
	/// <item>System.Collections.Generic.Dictionary`2</item>
	/// <item>System.Collections.Specialized.HybridDictionary</item>
	/// <item>System.Collections.Specialized.ListDictionary</item>
	/// </list>
	/// </para>
	///
	/// <para>
	/// Converts to
	/// <list type="bullet">
	/// <item>CsoGateway.Collections.Dictionary</item>
	/// </list>
	/// </para>
	/// </summary>
	public class DictionaryToClientSideConverter : IToClientSideConverter
	{
		/// <summary>
		/// Generates a string of javascript code that, when evaluated, creates an instance of CsoGateway.Collections.Dictionary
		/// that is the client side equivalent of the given object.
		/// The generated string is appended in the given StringBuffer. 
		/// </summary>
		/// <param name="sourceObject">An instance of one of the accepted type of Dictionary-like collections.</param>
		/// <param name="builder">The StringBuilder to write the generated javascript code to.</param>
		public void RenderObjectInstantiation(object sourceObject, StringBuilder builder)
		{
			IDictionary dictionaryObject = (IDictionary)sourceObject;

			object[] keys = new object[dictionaryObject.Count];
			object[] values = new object[dictionaryObject.Count];

			dictionaryObject.Keys.CopyTo(keys, 0);
			dictionaryObject.Values.CopyTo(values, 0);

			builder.Append("new CsoGateway.Collections.Dictionary(");

			for (int i = 0; i < dictionaryObject.Count; ++i)
			{
				ToClientSideMainConverter.RenderCsoCompatibleObject(keys[i], builder);
				builder.Append(',');
				ToClientSideMainConverter.RenderCsoCompatibleObject(values[i], builder);

				if (i < dictionaryObject.Count - 1)
					builder.Append(',');
			}

			builder.Append(')');

		}
	}

	/// <summary>
	/// <para>
	/// Provides methods to convert an instance of System.Collections.Specialized.StringDictionary into an instance of CsoGateway.Collections.Dictionary
	/// </para>
	/// 
	/// <para>
	/// Converter for
	/// <list type="bullet">
	/// <item>System.Collections.Specialized.StringDictionary</item>
	/// </list>
	/// </para>
	///
	/// <para>
	/// Converts to
	/// <list type="bullet">
	/// <item>CsoGateway.Collections.Dictionary</item>
	/// </list>
	/// </para>
	/// </summary>
	public class StringDictionaryToClientSideConverter : IToClientSideConverter
	{
		/// <summary>
		/// Generates a string of javascript code that, when evaluated, creates an instance of CsoGateway.Collections.Dictionary
		/// that is the client side equivalent of the given instance of System.Collections.Specialized.StringDictionnary.
		/// The generated string is appended in the given StringBuffer. 
		/// </summary>
		/// <param name="sourceObject">An instance of System.Collections.Specialized.StringDictionnary.</param>
		/// <param name="builder">The StringBuilder to write the generated javascript code to.</param>
		public void RenderObjectInstantiation(object sourceObject, StringBuilder builder)
		{
			StringDictionary dictionaryObject = (StringDictionary)sourceObject;

			object[] keys = new object[dictionaryObject.Count];
			object[] values = new object[dictionaryObject.Count];

			dictionaryObject.Keys.CopyTo(keys, 0);
			dictionaryObject.Values.CopyTo(values, 0);

			builder.Append("new CsoGateway.Collections.Dictionary(");

			for (int i = 0; i < dictionaryObject.Count; ++i)
			{
				ToClientSideMainConverter.RenderCsoCompatibleObject(keys[i], builder);
				builder.Append(',');
				ToClientSideMainConverter.RenderCsoCompatibleObject(values[i], builder);

				if (i < dictionaryObject.Count - 1)
					builder.Append(',');
			}

			builder.Append(')');
		}
	}

	/// <summary>
	/// <para>
	/// Provides methods to convert an instance of System.Collections.Queue into an instance of CsoGateway.Collections.Queue
	/// </para>
	/// 
	/// <para>
	/// Converter for
	/// <list type="bullet">
	/// <item>System.Collections.Queue</item>
	/// </list>
	/// </para>
	///
	/// <para>
	/// Converts to
	/// <list type="bullet">
	/// <item>CsoGateway.Collections.Queue</item>
	/// </list>
	/// </para>
	/// </summary>
	public class QueueToClientSideConverter : IToClientSideConverter
	{
		/// <summary>
		/// Generates a string of javascript code that, when evaluated, creates an instance of CsoGateway.Collections.Queue
		/// that is the client side equivalent of the given instance of System.Collections.Queue.
		/// The generated string is appended in the given StringBuffer. 
		/// </summary>
		/// <param name="sourceObject">An instance of System.Collections.Queue.</param>
		/// <param name="builder">The StringBuilder to write the generated javascript code to.</param>
		public void RenderObjectInstantiation(object sourceObject, StringBuilder builder)
		{
			Queue queueObject = (Queue)sourceObject;

			builder.Append("new CsoGateway.Collections.Queue(");

			object[] elementsArray = queueObject.ToArray();

			for (int i = 0; i < elementsArray.Length; ++i)
			{
				ToClientSideMainConverter.RenderCsoCompatibleObject(elementsArray[i], builder);

				if (i < elementsArray.Length - 1)
					builder.Append(',');
			}

			builder.Append(')');

		}
	}

	/// <summary>
	/// <para>
	/// Provides methods to convert an instance of System.Collections.Generic.Queue into an instance of CsoGateway.Collections.Queue
	/// </para>
	/// 
	/// <para>
	/// Converter for
	/// <list type="bullet">
	/// <item>System.Collections.Generic.Queue</item>
	/// </list>
	/// </para>
	///
	/// <para>
	/// Converts to
	/// <list type="bullet">
	/// <item>CsoGateway.Collections.Queue</item>
	/// </list>
	/// </para>
	/// </summary>
	public class GenericQueueToClientSideConverter : IToClientSideConverter
	{
		/// <summary>
		/// Generates a string of javascript code that, when evaluated, creates an instance of CsoGateway.Collections.Queue
		/// that is the client side equivalent of the given instance of System.Collections.Generic.Queue`1.
		/// The generated string is appended in the given StringBuffer. 
		/// </summary>
		/// <param name="sourceObject">An instance of System.Collections.Generic.Queue`1.</param>
		/// <param name="builder">The StringBuilder to write the generated javascript code to.</param>
		public void RenderObjectInstantiation(object sourceObject, StringBuilder builder)
		{
			ICollection queueObject = (ICollection)sourceObject;

			builder.Append("new CsoGateway.Collections.Queue(");

			object[] elementsArray = new object[queueObject.Count];
			queueObject.CopyTo(elementsArray, 0);

			for (int i = 0; i < elementsArray.Length; ++i)
			{
				ToClientSideMainConverter.RenderCsoCompatibleObject(elementsArray[i], builder);

				if (i < elementsArray.Length - 1)
					builder.Append(',');
			}

			builder.Append(')');

		}
	}

	/// <summary>
	/// <para>
	/// Provides methods to convert an instance of System.Collections.Stack into an instance of CsoGateway.Collections.Stack
	/// </para>
	/// 
	/// <para>
	/// Converter for
	/// <list type="bullet">
	/// <item>System.Collections.Stack</item>
	/// </list>
	/// </para>
	///
	/// <para>
	/// Converts to
	/// <list type="bullet">
	/// <item>CsoGateway.Collections.Stack</item>
	/// </list>
	/// </para>
	/// </summary>
	public class StackToClientSideConverter : IToClientSideConverter
	{
		/// <summary>
		/// Generates a string of javascript code that, when evaluated, creates an instance of CsoGateway.Collections.Stack
		/// that is the client side equivalent of the given instance of System.Collections.Stack.
		/// The generated string is appended in the given StringBuffer. 
		/// </summary>
		/// <param name="sourceObject">An instance of System.Collections.Stack.</param>
		/// <param name="builder">The StringBuilder to write the generated javascript code to.</param>
		public void RenderObjectInstantiation(object sourceObject, StringBuilder builder)
		{
			Stack stackObject = (Stack)sourceObject;

			builder.Append("new CsoGateway.Collections.Stack(");

			object[] elementsArray = stackObject.ToArray();

			for (int i = (elementsArray.Length-1); i >= 0; --i)
			{
				ToClientSideMainConverter.RenderCsoCompatibleObject(elementsArray[i], builder);

				if (i > 0)
					builder.Append(',');
			}

			builder.Append(')');
		}
	}

	/// <summary>
	/// <para>
	/// Provides methods to convert an instance of System.Collections.Generic.Stack into an instance of CsoGateway.Collections.Stack
	/// </para>
	/// 
	/// <para>
	/// Converter for
	/// <list type="bullet">
	/// <item>System.Collections.Generic.Stack</item>
	/// </list>
	/// </para>
	///
	/// <para>
	/// Converts to
	/// <list type="bullet">
	/// <item>CsoGateway.Collections.Stack</item>
	/// </list>
	/// </para>
	/// </summary>
	public class GenericStackToClientSideConverter : IToClientSideConverter
	{
		/// <summary>
		/// Generates a string of javascript code that, when evaluated, creates an instance of CsoGateway.Collections.Stack
		/// that is the client side equivalent of the given instance of System.Collections.Generic.Stack`1.
		/// The generated string is appended in the given StringBuffer. 
		/// </summary>
		/// <param name="sourceObject">An instance of System.Collections.Generic.Stack`1.</param>
		/// <param name="builder">The StringBuilder to write the generated javascript code to.</param>
		public void RenderObjectInstantiation(object sourceObject, StringBuilder builder)
		{
			ICollection stackObject = (ICollection)sourceObject;

			builder.Append("new CsoGateway.Collections.Stack(");

			object[] elementsArray = new object[stackObject.Count];
			stackObject.CopyTo(elementsArray, 0);

			for (int i = (elementsArray.Length - 1); i >= 0; --i)
			{
				ToClientSideMainConverter.RenderCsoCompatibleObject(elementsArray[i], builder);

				if (i > 0)
					builder.Append(',');
			}

			builder.Append(')');

		}
	}

	/// <summary>
	/// <para>
	/// Provides methods to convert objects of various types into an instance of CsoGateway.Collections.SortedList
	/// </para>
	/// 
	/// <para>
	/// Converter for
	/// <list type="bullet">
	/// <item>System.Collections.SortedList</item>
	/// <item>System.Collections.Generic.SortedList`2</item>
	/// <item>System.Collections.Generic.SortedDictionary`2</item>
	/// <item>System.Collections.Specialized.OrderedDictionary</item>
	/// </list>
	/// </para>
	///
	/// <para>
	/// Converts to
	/// <list type="bullet">
	/// <item>CsoGateway.Collections.SortedList</item>
	/// </list>
	/// </para>
	/// </summary>
	public class SortedListToClientSideConverter : IToClientSideConverter
	{
		/// <summary>
		/// Generates a string of javascript code that, when evaluated, creates an instance of CsoGateway.Collections.SortedList
		/// that is the client side equivalent of the given object.
		/// The generated string is appended in the given StringBuffer. 
		/// </summary>
		/// <param name="sourceObject">An instance of one of the supported sorted list-like types.</param>
		/// <param name="builder">The StringBuilder to write the generated javascript code to.</param>
		public void RenderObjectInstantiation(object sourceObject, StringBuilder builder)
		{
			IDictionary dictionaryObject = (IDictionary)sourceObject;

			object[] keys = new object[dictionaryObject.Count];
			object[] values = new object[dictionaryObject.Count];

			dictionaryObject.Keys.CopyTo(keys, 0);
			dictionaryObject.Values.CopyTo(values, 0);

			builder.Append("new CsoGateway.Collections.SortedList(");

			for (int i = 0; i < dictionaryObject.Count; ++i)
			{
				ToClientSideMainConverter.RenderCsoCompatibleObject(keys[i], builder);
				builder.Append(',');
				ToClientSideMainConverter.RenderCsoCompatibleObject(values[i], builder);

				if (i < dictionaryObject.Count - 1)
					builder.Append(',');
			}

			builder.Append(')');
		}
	}

	/// <summary>
	/// <para>
	/// Provides methods to convert instances of System.Collections.Specialized.NameValueCollection into an instance of CsoGateway.Collections.NameValueCollection
	/// </para>
	/// 
	/// <para>
	/// Converter for
	/// <list type="bullet">
	/// <item>System.Collections.Specialized.NameValueCollection</item>
	/// </list>
	/// </para>
	///
	/// <para>
	/// Converts to
	/// <list type="bullet">
	/// <item>CsoGateway.Collections.NameValueCollection</item>
	/// </list>
	/// </para>
	/// </summary>
	public class NameValueCollectionToClientSideConverter : IToClientSideConverter
	{
		/// <summary>
		/// Generates a string of javascript code that, when evaluated, creates an instance of CsoGateway.Collections.NameValueCollection
		/// that is the client side equivalent of the given instance of System.Collections.Specialized.NameValueCollection.
		/// The generated string is appended in the given StringBuffer. 
		/// </summary>
		/// <param name="sourceObject">An instance of System.Collections.Specialized.NameValueCollection.</param>
		/// <param name="builder">The StringBuilder to write the generated javascript code to.</param>
		public void RenderObjectInstantiation(object sourceObject, StringBuilder builder)
		{
			NameValueCollection nvcObject = (NameValueCollection)sourceObject;

			builder.Append("new CsoGateway.Collections.NameValueCollection(");
			string[] values;
			for (int i = 0; i < nvcObject.Keys.Count; ++i)
			{
				ToClientSideMainConverter.RenderCsoCompatibleObject(nvcObject.Keys[i], builder);
				builder.Append(",[");
				values = nvcObject.GetValues(i);
				for (int j = 0; j < values.Length; ++j)
				{
					ToClientSideMainConverter.RenderCsoCompatibleObject(values[j], builder);

					if (j < values.Length - 1)
						builder.Append(',');
				}
				builder.Append(']');

				if (i < nvcObject.Keys.Count - 1)
					builder.Append(',');
			}

			builder.Append(")");
			
		}
	}
}
